home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / showlfssegment / showlfssegment.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-12  |  16.5 KB  |  575 lines

  1. /* 
  2.  * showlfssegment.c --
  3.  *
  4.  *    The showlfssegment program - Show the segment usage of an
  5.  *    LFS file system.
  6.  *
  7.  * Copyright 1989 Regents of the University of California
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /sprite/src/admin/showlfssegment/RCS/showlfssegment.c,v 1.1 92/03/11 21:54:25 shirriff Exp $ SPRITE (Berkeley)";
  19. #endif /* not lint */
  20.  
  21. #include "../lfslib/lfslib.h"
  22. #ifdef _HAS_PROTOTYPES
  23. #include <varargs.h>
  24. #endif
  25.  
  26. #include <sprite.h>
  27. #include <stdio.h>
  28. #include <option.h>
  29. #include <sys/types.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <sys/file.h>
  33.  
  34.  
  35. int    blockSize = 512;
  36. int    offset = 64;
  37.  
  38. char    *deviceName;
  39.  
  40. Option optionArray[] = {
  41.     {OPT_DOC, (char *) NULL,  (char *) NULL,
  42.     "This program shows the usage of an LFS file system.\n Synopsis: \"showLfsUsage [switches] deviceName\"\n Command-line switches are:"},
  43.     {OPT_INT, "blockSize", (Address) &blockSize, 
  44.     "Block size of file system."},
  45.     {OPT_INT, "offset", (Address) &offset, 
  46.     "Offset into device to start file system."},
  47. };
  48. /*
  49.  * Forward routine declartions. 
  50.  */
  51.  
  52. static void PrintSegUsageSummary _ARGS_((Lfs *lfsPtr, LfsSeg *segPtr,
  53.     int startAddress, int offset, LfsSegSummaryHdr *segSummaryHdrPtr));
  54. static void PrintDescMapSummary _ARGS_((Lfs *lfsPtr, LfsSeg *segPtr, 
  55.     int startAddress, int offset, LfsSegSummaryHdr *segSummaryHdrPtr));
  56. static void PrintFileLayoutSummary _ARGS_((Lfs *lfsPtr, LfsSeg *segPtr,
  57.     int startAddr, int offset, LfsSegSummaryHdr *segSummaryHdrPtr));
  58. static void ShowDirLogBlock _ARGS_((LfsDirOpLogBlockHdr *hdrPtr, int addr));
  59.  
  60. static char *DirOpFlagsToString _ARGS_((int opFlags));
  61. static char *FileTypeToString _ARGS_((int fileType));
  62.  
  63. static void PrintSegmentContents _ARGS_((Lfs *lfsPtr, int segNum));
  64. extern void panic();
  65.  
  66.  
  67. /*
  68.  *----------------------------------------------------------------------
  69.  *
  70.  * main --
  71.  *
  72.  *    Main routine of mklfs - parse arguments and do the work.
  73.  *
  74.  * Results:
  75.  *    None.
  76.  *
  77.  * Side effects:
  78.  *    None.
  79.  *
  80.  *----------------------------------------------------------------------
  81.  */
  82.  
  83. int
  84. main(argc,argv)
  85.     int    argc;
  86.     char *argv[];
  87. {
  88.     Lfs    *lfsPtr;
  89.     int    segNum;
  90.  
  91.  
  92.  
  93.     argc = Opt_Parse(argc, argv, optionArray, Opt_Number(optionArray), 0);
  94.     if (argc != 3) { 
  95.          Opt_PrintUsage(argv[0], optionArray, Opt_Number(optionArray));
  96.      exit(1);
  97.      segNum = 0; /* Lint avoidance. */
  98.     } else {
  99.     deviceName = argv[1];
  100.     segNum = atoi(argv[2]);
  101.     }
  102.     lfsPtr = LfsLoadFileSystem(argv[0], deviceName, blockSize, offset,
  103.                  O_RDONLY);
  104.     if (lfsPtr == (Lfs *) NULL) {
  105.     exit(1);
  106.     }
  107.     if ((segNum < 0 || segNum >= lfsPtr->superBlock.usageArray.numberSegments) &&
  108.     (segNum != -1) ) {
  109.     fprintf(stderr, "%s: Bad segment number %s\n", argv[0], argv[2]);
  110.     exit(1);
  111.     }
  112.     if (segNum == 0) {
  113.     for (segNum = 1; segNum < lfsPtr->superBlock.usageArray.numberSegments;
  114.         segNum++) { 
  115.  
  116.  
  117.         printf("Segment number %d\n", segNum);
  118.         PrintSegmentContents(lfsPtr, segNum);
  119.     }
  120.     } else {
  121.  
  122.  
  123.     printf("Segment number %d\n", segNum);
  124.     PrintSegmentContents(lfsPtr, segNum);
  125.     }
  126.  
  127.     exit(0);
  128.     return 0;
  129. }
  130.  
  131.  
  132. /*
  133.  *----------------------------------------------------------------------
  134.  *
  135.  * PrintSegmentContents --
  136.  *
  137.  *    Print out the contents of an LFS segement.
  138.  *
  139.  * Results:
  140.  *    None.
  141.  *
  142.  * Side effects:
  143.  *    None.
  144.  *
  145.  *----------------------------------------------------------------------
  146.  */
  147. static void
  148. PrintSegmentContents(lfsPtr, segNum)
  149.     Lfs    *lfsPtr;    /* File system. */
  150.     int    segNum;        /* LfsSegment number. */
  151. {
  152.     LfsSeg    *segPtr;
  153.     int startAddr;
  154.     char *summaryLimitPtr, *summaryPtr;
  155.     LfsSegSummary *segSummaryPtr;
  156.     LfsSegSummaryHdr *segSummaryHdrPtr;
  157.     int blockOffset;
  158.  
  159.  
  160.     blockOffset = 0;
  161.     segPtr = LfsSegInit(lfsPtr, segNum);
  162.     startAddr = LfsSegStartAddr(segPtr) + LfsSegSizeInBlocks(lfsPtr);
  163.     do { 
  164.     segSummaryPtr = (LfsSegSummary *) 
  165.             LfsSegFetchBlock(segPtr, blockOffset, blockSize);
  166.     if (segSummaryPtr->size == 0) {
  167.         LfsSegReleaseBlock(segPtr, (char *) segSummaryPtr);
  168.         break;
  169.     }
  170.     if (segSummaryPtr->magic != LFS_SEG_SUMMARY_MAGIC) {
  171.         fprintf(stderr,"%s: Bad magic number 0x%x for summary region of segment %d\n", deviceName, segSummaryPtr->magic, segNum);
  172.         break;
  173.     }
  174.     printf("Addr %d Summary Time %d PrevSeg %d NextSeg %d bytes %d NextSum %d\n",
  175.         startAddr-blockOffset,
  176.         segSummaryPtr->timestamp, segSummaryPtr->prevSeg, 
  177.         segSummaryPtr->nextSeg,
  178.         segSummaryPtr->size, segSummaryPtr->nextSummaryBlock);
  179.     blockOffset++;
  180.     summaryLimitPtr = (char *) segSummaryPtr + segSummaryPtr->size;
  181.     summaryPtr = (char *) (segSummaryPtr + 1);
  182.     while (summaryPtr < summaryLimitPtr) {
  183.        segSummaryHdrPtr = (LfsSegSummaryHdr *) summaryPtr;
  184.        if (segSummaryHdrPtr->lengthInBytes == 0) {
  185.         break;
  186.        }
  187.        switch (segSummaryHdrPtr->moduleType) { 
  188.        case LFS_SEG_USAGE_MOD:
  189.           PrintSegUsageSummary(lfsPtr, segPtr, startAddr - blockOffset, blockOffset, 
  190.                 segSummaryHdrPtr);
  191.            break;
  192.        case LFS_DESC_MAP_MOD:
  193.           PrintDescMapSummary(lfsPtr, segPtr, startAddr - blockOffset, blockOffset, 
  194.                 segSummaryHdrPtr);
  195.            break;
  196.        case LFS_FILE_LAYOUT_MOD:
  197.           PrintFileLayoutSummary(lfsPtr, segPtr,startAddr - blockOffset, blockOffset, 
  198.                 segSummaryHdrPtr);
  199.         break;
  200.        default: {
  201.         fprintf(stderr,"%s:CheckSummary: Unknown module type %d at %d, Size %d Blocks %d\n",
  202.             deviceName, segSummaryHdrPtr->moduleType, startAddr - blockOffset, segSummaryHdrPtr->lengthInBytes, segSummaryHdrPtr->numDataBlocks);
  203.         break;
  204.         }
  205.        }
  206.        summaryPtr += segSummaryHdrPtr->lengthInBytes;
  207.        blockOffset += (segSummaryHdrPtr->numDataBlocks-1);
  208.        }
  209.        if (segSummaryPtr->nextSummaryBlock == -1) { 
  210.        blockOffset = 0;
  211.        } else {
  212.        blockOffset = segSummaryPtr->nextSummaryBlock-1;
  213.        }
  214.        LfsSegReleaseBlock(segPtr, (char *) segSummaryPtr);
  215.     } while( blockOffset != 0);
  216.     LfsSegRelease(segPtr);
  217. }
  218.  
  219. /*
  220.  *----------------------------------------------------------------------
  221.  *
  222.  * PrintSegUsageSummary --
  223.  *
  224.  *    Check the segment summary regions for the seg usage map.
  225.  *
  226.  * Results:
  227.  *    None.
  228.  *
  229.  * Side effects:
  230.  *    None.
  231.  *
  232.  *----------------------------------------------------------------------
  233.  */
  234. static void
  235. PrintSegUsageSummary(lfsPtr, segPtr, startAddress, offset, segSummaryHdrPtr) 
  236.     Lfs    *lfsPtr;
  237.     LfsSeg *segPtr;
  238.     int startAddress;
  239.     int offset;
  240.     LfsSegSummaryHdr *segSummaryHdrPtr;
  241. {
  242.     int blocks, *blockArray, i, startAddr, fsBlocks;
  243.  
  244.     fsBlocks = lfsPtr->superBlock.usageArray.stableMem.blockSize/blockSize;
  245.     blocks = (segSummaryHdrPtr->lengthInBytes - sizeof(LfsSegSummaryHdr)) /
  246.                 sizeof(int);
  247.     if (blocks * fsBlocks != segSummaryHdrPtr->numDataBlocks) {
  248.     fprintf(stderr,"%s:PrintSegUsageSummary: Wrong block count; is %d should be %s\n", deviceName, blocks * fsBlocks, segSummaryHdrPtr->numDataBlocks);
  249.     }
  250.     blockArray = (int *) (segSummaryHdrPtr + 1);
  251.     for (i = 0; i < blocks; i++) {
  252.     startAddr = startAddress - i * fsBlocks - fsBlocks;
  253.     if ((blockArray[i] < 0) || 
  254.         (blockArray[i] > lfsPtr->superBlock.usageArray.stableMem.maxNumBlocks)){
  255.        fprintf(stderr,"%s:PrintSegUsageSummary: Bad block number %d at %d\n",
  256.             deviceName,blockArray[i], startAddr);
  257.         continue;
  258.     }
  259.     printf("Addr %d UsageArray Block %d %s\n", startAddr, blockArray[i],
  260.         (LfsGetUsageArrayBlockIndex(lfsPtr,blockArray[i]) == 
  261.             startAddr) ? "alive" : "dead");
  262.     }
  263.  
  264. }
  265.  
  266. /*
  267.  *----------------------------------------------------------------------
  268.  *
  269.  * PrintDescMapSummary --
  270.  *
  271.  *    Check the segment summary regions for the desc map.
  272.  *
  273.  * Results:
  274.  *    None.
  275.  *
  276.  * Side effects:
  277.  *    None.
  278.  *
  279.  *----------------------------------------------------------------------
  280.  */
  281. static void
  282. PrintDescMapSummary(lfsPtr, segPtr, startAddress, offset, segSummaryHdrPtr) 
  283.     Lfs    *lfsPtr;
  284.     LfsSeg *segPtr;
  285.     int startAddress;
  286.     int offset;
  287.     LfsSegSummaryHdr *segSummaryHdrPtr;
  288. {
  289.     int blocks, *blockArray, i, startAddr, fsBlocks;
  290.  
  291.     fsBlocks = lfsPtr->superBlock.descMap.stableMem.blockSize/blockSize;
  292.     blocks = (segSummaryHdrPtr->lengthInBytes - sizeof(LfsSegSummaryHdr)) /
  293.                 sizeof(int);
  294.     if (blocks * fsBlocks != segSummaryHdrPtr->numDataBlocks) {
  295.     fprintf(stderr,"%s:PrintDescMapSummary: Wrong block count; is %d should be %s\n", deviceName,blocks * fsBlocks, segSummaryHdrPtr->numDataBlocks);
  296.     }
  297.     blockArray = (int *) (segSummaryHdrPtr + 1);
  298.     for (i = 0; i < blocks; i++) {
  299.     startAddr = startAddress - i * fsBlocks - fsBlocks;
  300.     if ((blockArray[i] < 0) || 
  301.         (blockArray[i] > lfsPtr->superBlock.descMap.stableMem.maxNumBlocks)){
  302.        fprintf(stderr,"%s:PrintDescMapSummary: Bad block number %d at %d\n",
  303.             deviceName,blockArray[i], startAddr);
  304.         continue;
  305.     }
  306.     printf("Addr %d DescMap Block %d %s\n", startAddr, blockArray[i],
  307.         (LfsGetDescMapBlockIndex(lfsPtr,blockArray[i]) == 
  308.             startAddr) ? "alive" : "dead");
  309.     }
  310.  
  311. }
  312.  
  313. /*
  314.  *----------------------------------------------------------------------
  315.  *
  316.  * PrintFileLayoutSummary --
  317.  *
  318.  *    Check the segment summary regions for the file layout code.
  319.  *
  320.  * Results:
  321.  *    None.
  322.  *
  323.  * Side effects:
  324.  *    None.
  325.  *
  326.  *----------------------------------------------------------------------
  327.  */
  328. static void
  329. PrintFileLayoutSummary(lfsPtr, segPtr, startAddr, offset, segSummaryHdrPtr) 
  330.     Lfs    *lfsPtr;
  331.     LfsSeg  *segPtr;
  332.     int startAddr;
  333.     int offset;
  334.     LfsSegSummaryHdr *segSummaryHdrPtr;
  335. {
  336.     char *summaryPtr, *limitPtr;
  337.     int descMapBlocks;
  338.     int startAddress,  ssize;
  339.     LfsDescMapEntry *entryPtr;
  340.     LfsFile    *filePtr;
  341.     ReturnStatus status;
  342.     Boolean dead;
  343.     int sizeJunk;
  344.  
  345.     ssize = LfsSegSize(lfsPtr);
  346.  
  347.  
  348.     startAddress = startAddr;
  349.     descMapBlocks = lfsPtr->superBlock.descMap.stableMem.blockSize/blockSize;
  350.     summaryPtr = (char *) (segSummaryHdrPtr + 1);
  351.     limitPtr = summaryPtr + segSummaryHdrPtr->lengthInBytes - 
  352.             sizeof(LfsSegSummaryHdr);
  353.     while (summaryPtr < limitPtr) {
  354.     switch (*(unsigned short *) summaryPtr) {
  355.     case LFS_FILE_LAYOUT_DESC: {
  356.         int        fileNumber;
  357.         int        slot;
  358.         LfsFileDescriptor    *descPtr;
  359.         descPtr = (LfsFileDescriptor *) LfsSegFetchBlock(segPtr, offset, 
  360.                         descMapBlocks*blockSize);
  361.         offset += descMapBlocks;
  362.         startAddress -= descMapBlocks;
  363.         for (slot = 0; slot < lfsPtr->superBlock.fileLayout.descPerBlock; 
  364.         slot++) {
  365.         int addr;
  366.         /*
  367.          * The descriptor block is terminated by an unallocated
  368.          * descriptor.
  369.          */
  370.         if (!(descPtr[slot].common.flags & FSDM_FD_ALLOC)) {
  371.             break;
  372.         }
  373.  
  374.         addr = startAddress + (slot * sizeof(LfsFileDescriptor))/
  375.                         blockSize;
  376.         fileNumber = descPtr[slot].fileNumber;
  377.         if ((fileNumber < 0) || 
  378.             (fileNumber >= lfsPtr->superBlock.descMap.maxDesc)) {
  379.            fprintf(stderr,"%s:PrintFileLayoutSummary: bad file number %d in desc block at %d\n", deviceName, fileNumber, startAddress);
  380.            continue;
  381.         }
  382.         entryPtr = LfsGetDescMapEntry(lfsPtr, fileNumber);
  383.         printf("Addr %d Descriptor %s %d len %d %s\n",
  384.             startAddress,
  385.             FileTypeToString(descPtr[slot].common.fileType),
  386.             descPtr[slot].fileNumber,
  387.             descPtr[slot].common.lastByte+1,
  388.             ((entryPtr == (LfsDescMapEntry*) NIL) ||
  389.              (entryPtr->blockAddress != startAddress)) ? "dead" :
  390.              "alive");
  391.          }
  392.         /*
  393.          * Skip over the summary bytes describing this block. 
  394.          */
  395.         summaryPtr += sizeof(LfsFileLayoutDesc);
  396.         LfsSegReleaseBlock(segPtr, (char *) descPtr);
  397.         break;
  398.     }
  399.     case LFS_FILE_LAYOUT_DATA: {
  400.         int    *blockArray;
  401.         int              i;
  402.         LfsFileLayoutSummary *fileSumPtr;
  403.         int firstBlock;
  404.         /*
  405.          * We ran into a data block. If it is still alive bring it into
  406.          * the cache. 
  407.          */
  408.          fileSumPtr = (LfsFileLayoutSummary *) summaryPtr;
  409.         if ((fileSumPtr->fileNumber < 0) || 
  410.         (fileSumPtr->fileNumber >= lfsPtr->superBlock.descMap.maxDesc)) {
  411.            fprintf(stderr,"%s:PrintFileLayoutSummary: bad file number %d at %d\n", deviceName, fileSumPtr->fileNumber, startAddress);
  412.            goto out;
  413.         }
  414.         status = LfsFileOpen(lfsPtr, fileSumPtr->fileNumber, &filePtr);
  415.         if (status != SUCCESS) {
  416.         dead = TRUE;
  417.         } else {
  418.         dead = FALSE;
  419.         }
  420.  
  421.         printf("Addr %d File %d blocks %d version %d dataBlocks %d %s\n",
  422.         startAddress - fileSumPtr->numBlocks,
  423.         fileSumPtr->fileNumber, fileSumPtr->numBlocks,
  424.         fileSumPtr->truncVersion,
  425.         fileSumPtr->numDataBlocks,
  426.         dead ? "dead" : "alive");
  427.  
  428.         /*
  429.          * For each block ... 
  430.          */
  431.         blockArray = (int *)(summaryPtr + sizeof(LfsFileLayoutSummary));
  432.         firstBlock = fileSumPtr->numBlocks -
  433.          (fileSumPtr->numDataBlocks-1) * FS_BLOCK_SIZE/blockSize;
  434.         for (i = 0; i < fileSumPtr->numDataBlocks; i++) {
  435.         int addr, blocks;
  436.  
  437.         addr = startAddress - i*FS_BLOCK_SIZE/blockSize - firstBlock;
  438.         blocks = (i == 0) ? firstBlock : (FS_BLOCK_SIZE/blockSize);
  439.         printf("Addr %d File %d block %d %s\n",
  440.             addr, fileSumPtr->fileNumber, blockArray[i],
  441.             (!dead && LfsFileBlockAddr(filePtr,blockArray[i], &sizeJunk) ==  addr) ? "alive" : "dead");
  442.         }
  443.         if (!dead) {
  444.         LfsFileClose(filePtr);
  445.         }
  446.         out:
  447.         startAddress = startAddress - fileSumPtr->numBlocks;
  448.         offset += fileSumPtr->numBlocks;
  449.         summaryPtr += sizeof(LfsFileLayoutSummary) + 
  450.                 fileSumPtr->numDataBlocks * sizeof(int); 
  451.         break;
  452.       }
  453.  
  454.     case LFS_FILE_LAYOUT_DIR_LOG: {
  455.         LfsFileLayoutLog    *logSumPtr;
  456.         int            numBlocks;
  457.         int            i, addr, blocks;
  458.         LfsDirOpLogBlockHdr *hdrPtr = (LfsDirOpLogBlockHdr *) NIL;
  459.  
  460.         /* 
  461.          * Directory log info is not needed during clean so we 
  462.          * just skip over it.
  463.          */
  464.          logSumPtr = (LfsFileLayoutLog *) summaryPtr;
  465.          summaryPtr = summaryPtr + sizeof(LfsFileLayoutLog);
  466.          numBlocks = logSumPtr->numBlocks;
  467.          addr = startAddress;
  468.          for (i = 0; i < logSumPtr->numDataBlocks; i++) {
  469.         if (numBlocks > FS_BLOCK_SIZE/blockSize) {
  470.             blocks = FS_BLOCK_SIZE/blockSize;
  471.         } else {
  472.             blocks = numBlocks;
  473.         }
  474.  
  475.             hdrPtr = (LfsDirOpLogBlockHdr *)
  476.              LfsSegFetchBlock(segPtr, offset, blocks*blockSize);
  477.         addr -= blocks;
  478.         offset += blocks;
  479.         if (hdrPtr->magic != LFS_DIROP_LOG_MAGIC) {
  480.             fprintf(stderr,"Bad dir op log magic number.\n");
  481.         }
  482.         ShowDirLogBlock(hdrPtr, addr);
  483.         LfsSegReleaseBlock(segPtr, (char *) hdrPtr);
  484.         }
  485.  
  486.         startAddress = startAddress - logSumPtr->numBlocks;
  487.         break;
  488.     }
  489.     case LFS_FILE_LAYOUT_DBL_INDIRECT: 
  490.     case LFS_FILE_LAYOUT_INDIRECT: 
  491.     default: {
  492.         panic("Unknown type");
  493.     }
  494.       }
  495.     }
  496.  
  497. }
  498.  
  499. static void
  500. ShowDirLogBlock(hdrPtr, addr)
  501.     LfsDirOpLogBlockHdr *hdrPtr;
  502.     int addr;
  503. {
  504.     LfsDirOpLogEntry *entryPtr, *limitPtr;
  505.  
  506.     limitPtr = (LfsDirOpLogEntry *) (((char *) hdrPtr) + hdrPtr->size);
  507.     entryPtr = (LfsDirOpLogEntry *) (hdrPtr+1);
  508.     while (entryPtr < limitPtr) {
  509.     entryPtr->dirEntry.fileName[entryPtr->dirEntry.nameLength] = '\0';
  510.     printf("Addr %d LogSeqNum %d %s %d \"%s\" links %d in %d at %d\n",
  511.         addr,
  512.         entryPtr->hdr.logSeqNum, 
  513.         DirOpFlagsToString(entryPtr->hdr.opFlags), 
  514.         entryPtr->dirEntry.fileNumber, 
  515.         entryPtr->dirEntry.fileName,
  516.         entryPtr->hdr.linkCount,
  517.         entryPtr->hdr.dirFileNumber,
  518.         entryPtr->hdr.dirOffset);
  519.     entryPtr = (LfsDirOpLogEntry *) 
  520.              (((char *)entryPtr) + LFS_DIR_OP_LOG_ENTRY_SIZE(entryPtr));
  521.     }
  522.  
  523. }
  524.  
  525. static char *
  526. DirOpFlagsToString(opFlags)
  527.     int opFlags;
  528. {
  529.     int op = opFlags & FSDM_LOG_OP_MASK;
  530.     char buffer[128];
  531.     static char *opcodes[] = {"UNKNOWN", "CREATE", "UNLINK", "LINK", 
  532.             "RENAME_DELETE", "RENAME_LINK", "RENAME_LINK", 
  533.             "UNKNOWN"};
  534.     if ((op < 0) || (op >= sizeof(opcodes)/sizeof(opcodes[0]))) {
  535.     op = sizeof(opcodes)/sizeof(opcodes[0])-1;
  536.     }
  537.     strcpy(buffer,opcodes[op]);
  538.     if (opFlags & FSDM_LOG_STILL_OPEN) {
  539.     strcat(buffer, "-OPEN");
  540.     opFlags ^= FSDM_LOG_STILL_OPEN;
  541.     }
  542.     if (opFlags & FSDM_LOG_START_ENTRY) {
  543.     strcat(buffer, "-START");
  544.     opFlags ^= FSDM_LOG_START_ENTRY;
  545.     }
  546.     if (opFlags & FSDM_LOG_END_ENTRY) {
  547.     strcat(buffer, "-END");
  548.     opFlags ^= FSDM_LOG_END_ENTRY;
  549.     }
  550.     if (opFlags & FSDM_LOG_IS_DIRECTORY) {
  551.     strcat(buffer, "-DIR");
  552.     opFlags ^= FSDM_LOG_IS_DIRECTORY;
  553.     }
  554.     if (opFlags & ~FSDM_LOG_OP_MASK) {
  555.     strcat(buffer, "-UNKNOWN");
  556.     }
  557.     return buffer;
  558.  
  559. }
  560. static char *
  561. FileTypeToString(fileType)
  562.     int fileType;
  563. {
  564.     static char *names[] = { "File", "Dir", "Symlink", "Rmtlink", "Dev", 
  565.                  "Rmtdev", "Pipe", "NamedPipe", "Pdev", "Pfs",
  566.                  "XtraFile", "Unknown"};
  567.  
  568.     if ((fileType < 0) || (fileType >= sizeof(names)/sizeof(names[0]))) {
  569.     fileType = sizeof(names)/sizeof(names[0])-1;
  570.     }
  571.     return names[fileType];
  572. }
  573.  
  574.  
  575.